﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Linq;
using A2DFramework.CacheService.CacheProvider.LocalCache;

namespace A2DFramework.CacheService.Configuration
{
    public static class CacheConfiguration
    {
        private const int defaultCacheChunkSize = Int32.MaxValue;
        private static Dictionary<string, Storage> _storages = new Dictionary<string, Storage>();
        public static Dictionary<string, Storage> Storages
        {
            get
            {
                return _storages;
            }
        }

        static CacheConfiguration()
        {
            XElement root = XElement.Load(System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "A2D.config"));

            root = root.Element("CacheStorages");
            if (root == null)
                throw new Exception("CacheStorages node not exists");

            foreach (var elm in root.Elements("Storage"))
            {
                Storage storage = new Storage();

                //global
                storage.Location = elm.Attribute("Location").Value;
                storage.Scope = (StorageScope)Enum.Parse(typeof(StorageScope), elm.Attribute("Scope").Value);

                //LocalCacheSetting
                storage.LocalCacheSetting_CacheAlgorithm = (CacheType)Enum.Parse(typeof(CacheType), elm.Element("LocalCacheSetting").Element("CacheAlgorithm").Value);
                storage.LocalCacheSetting_CacheCapacity = int.Parse(elm.Element("LocalCacheSetting").Element("CacheCapacity").Value);

                storage.DistributedCacheSetting_MaxCacheEntitySize = defaultCacheChunkSize;

                if (elm.Element("DistributedCacheSetting") != null)
                {
                    //DistributedCacheSetting
                    storage.DistributedCacheSetting_MaxCacheEntitySize = int.Parse(elm.Element("DistributedCacheSetting").Element("MaxCacheEntitySize").Value);

                    //DistributedCacheSetting PeerCacheServers list
                    foreach (var cacheServerElm in elm.Element("DistributedCacheSetting").Element("PeerCacheServers").Elements("CacheServer"))
                    {
                        CacheServerInfo srv = new CacheServerInfo();
                        srv.ServerAddress = cacheServerElm.Element("ServerAddress").Value;
                        srv.ServerPort = int.Parse(cacheServerElm.Element("ServerPort").Value);
                        srv.ServerType = (CacheServerType)Enum.Parse(typeof(CacheServerType), cacheServerElm.Element("ServerType").Value);
                        storage.DistributedCacheSetting_PeerCacheServers.Add(srv);
                    }

                    //DistributedCacheSetting BackupCacheServer
                    if (elm.Element("DistributedCacheSetting").Element("BackupCacheServer") != null)
                    {
                        var cacheServerElm = elm.Element("DistributedCacheSetting").Element("BackupCacheServer").Element("CacheServer");

                        CacheServerInfo srv = new CacheServerInfo();
                        srv.ServerAddress = cacheServerElm.Element("ServerAddress").Value;
                        srv.ServerPort = int.Parse(cacheServerElm.Element("ServerPort").Value);
                        srv.ServerType = (CacheServerType)Enum.Parse(typeof(CacheServerType), cacheServerElm.Element("ServerType").Value);

                        storage.DistributedCacheSetting_BackupCacheServer = srv;
                    }
                }
                _storages[storage.Location] = storage;
            }

            foreach (string key in _storages.Keys)
            { 
                Storage storage=_storages[key];

                if (storage.DistributedCacheSetting_PeerCacheServers != null)
                {
                    foreach (CacheServerInfo csInfo in storage.DistributedCacheSetting_PeerCacheServers)
                    {
                        if (string.IsNullOrWhiteSpace(csInfo.ServerAddress))
                            throw new Exception("Peer cache server cannot be empty");
                        if (csInfo.ServerPort <= 0)
                            throw new Exception("Peer cache server's port cannot less then 0");
                    }
                }


                if (storage.DistributedCacheSetting_BackupCacheServer != null)
                {
                    if (string.IsNullOrWhiteSpace(storage.DistributedCacheSetting_BackupCacheServer.ServerAddress))
                        throw new Exception("Backup cache server cannot be empty");
                    if (storage.DistributedCacheSetting_BackupCacheServer.ServerPort <= 0)
                        throw new Exception("Backup cache server's port cannot less then 0");
                }
            }
        }
    }
}
